package com.nbstar.film.spider;

import com.nbstar.film.spider.domain.ProxyInfo;
import com.nbstar.film.spider.proxy.proxyee.intercept.HttpProxyIntercept;
import com.nbstar.film.spider.proxy.proxyee.intercept.HttpProxyInterceptInitializer;
import com.nbstar.film.spider.proxy.proxyee.intercept.HttpProxyInterceptPipeline;
import com.nbstar.film.spider.proxy.proxyee.intercept.common.CertDownIntercept;
import com.nbstar.film.spider.proxy.proxyee.intercept.common.FullResponseIntercept;
import com.nbstar.film.spider.proxy.proxyee.server.HttpProxyServer;
import com.nbstar.film.spider.proxy.proxyee.server.HttpProxyServerConfig;
import com.nbstar.film.spider.proxy.proxyee.util.HttpUtil;
import com.nbstar.film.spider.thread.ProxyThread;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;

@Slf4j
public class NbStarProxy {
    public static void main(String[] args) {
        try {
            CrackProxyServer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void NormalHttpProxyServer() {
        HttpProxyServerConfig config = new HttpProxyServerConfig();
        config.setBossGroupThreads(1);
        config.setWorkerGroupThreads(1);
        config.setProxyGroupThreads(1);
        new HttpProxyServer()
                .serverConfig(config)
                .start(9999);
    }

    public static void CrackProxyServer() throws Exception {
        ProxyThread proxyThread = new ProxyThread();
        proxyThread.start();
        HttpProxyServerConfig config = new HttpProxyServerConfig();
        config.setHandleSsl(true);
        new HttpProxyServer()
                .serverConfig(config)
                .proxyInterceptInitializer(new HttpProxyInterceptInitializer() {
                    @Override
                    public void init(HttpProxyInterceptPipeline pipeline) {
                        pipeline.addLast(new CertDownIntercept());
                        pipeline.addLast(new HttpProxyIntercept() {
                            @Override
                            public void beforeRequest(Channel clientChannel, HttpRequest httpRequest,
                                                      HttpProxyInterceptPipeline pipeline) throws Exception {
                                log.info("beforeRequest");
                                //从代理池获取ip
                                try {
                                    ProxyInfo proxyInfo =  ProxyThread.ipPool.take();
                                    System.out.println(proxyInfo);
                                    String host = httpRequest.headers().get(HttpHeaderNames.HOST);
                                    String url;
                                    if (httpRequest.uri().indexOf("/") == 0) {
                                        if (httpRequest.uri().length() > 1) {
                                            url = host + httpRequest.uri();
                                        } else {
                                            url = host;
                                        }
                                    } else {
                                        url = httpRequest.uri();
                                    }
                                    log.info("将请求{}转发{}", url, proxyInfo.getProxy());
                                    String []infos = proxyInfo.getProxy().split(":");
                                    pipeline.getRequestProto().setHost(infos[0]);
                                    pipeline.getRequestProto().setPort(Integer.parseInt(infos[1]));
                                    pipeline.getRequestProto().setSsl(true);
                                    pipeline.beforeRequest(clientChannel, httpRequest);
                                } catch (InterruptedException e) {
                                    log.error(e.getMessage());
                                };
                            }
                        });
                        pipeline.addLast(new FullResponseIntercept() {

                            @Override
                            public boolean match(HttpRequest httpRequest, HttpResponse httpResponse, HttpProxyInterceptPipeline pipeline) {
                                //在匹配到百度首页时插入js
                                return HttpUtil.checkUrl(pipeline.getHttpRequest(), "*general_page*")
                                        && HttpUtil.isHtml(httpRequest, httpResponse);

                            }

                            @Override
                            public void handelResponse(HttpRequest httpRequest, FullHttpResponse httpResponse, HttpProxyInterceptPipeline pipeline) {
                                //打印原始响应信息
                                System.out.println(httpResponse.toString());
                                System.out.println(httpResponse.content().toString(Charset.defaultCharset()));
                                //修改响应头和响应体

                    /*int index = ByteUtil.findText(httpResponse.content(), "<head>");
                    ByteUtil.insertText(httpResponse.content(), index, "<script>alert(1)</script>");*/
                                httpResponse.content().writeBytes("<script>alert('hello proxyee')</script>".getBytes());
                                String content = httpResponse.content().toString(Charset.forName("UTF-8"));
                                int pos = content.indexOf("<script>") + "<script>".length();
                                StringBuffer sb = new StringBuffer(content);
                                String inspect = "Object.defineProperty(navigator, 'webdriver', {get:()=>undefined});";
                                sb.insert(pos, inspect);

                                httpResponse.replace(Unpooled.copiedBuffer(sb.toString().getBytes()));

                            }
                        });
                    }
                })
                .start(9999);
    }
}
